package com.tanhua.manage.service;

import cn.hutool.core.date.DateUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.tanhua.domain.vo.StatisticsVo;
import com.tanhua.manage.domain.AnalysisByDay;
import com.tanhua.manage.domain.Log;
import com.tanhua.manage.mapper.AnalysisByDayMapper;
import com.tanhua.manage.mapper.LogMapper;
import com.tanhua.manage.utils.ComputeUtil;
import com.tanhua.manage.vo.AnalysisSummaryVo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;

@Service
public class AnalysisByDayService extends ServiceImpl<AnalysisByDayMapper, AnalysisByDay> {


    @Autowired
    private AnalysisByDayMapper analysisByDayMapper;

    @Autowired
    private LogMapper logMapper;


    /**
     * 统计概要信息
     *
     * @return
     */
    public ResponseEntity summary() {
        //1. 得到今日与昨天的日期
        Date nowDate = new Date();
        String now = DateUtil.formatDate(nowDate);//默认日期格式： yyyy-MM-dd
        String yesterday = ComputeUtil.offsetDay(nowDate, -1);

        //2. 查询累计用户数
        AnalysisByDay analysisByDay = query().select("SUM(num_registered) numRegistered").one();
        Integer numRegistered = analysisByDay.getNumRegistered();


        //3. 查询新增用户、登陆次数、活跃用户（今日、昨天）
        AnalysisByDay todayAnalysisByDay = query().eq("record_date", now).one();
        AnalysisByDay yesterdayAnalysisByDay = query().eq("record_date", yesterday).one();

        //新增的用户数
        Integer todayNumRegistered = todayAnalysisByDay.getNumRegistered();
        Integer yesNumRegistered = yesterdayAnalysisByDay.getNumRegistered();

        //新增的登陆次数
        Integer todayNumLogin = todayAnalysisByDay.getNumLogin();
        Integer yesNumLogin = yesterdayAnalysisByDay.getNumLogin();

        //新增的登陆次数
        Integer todayNumActive = todayAnalysisByDay.getNumActive();
        Integer yesNumActive = yesterdayAnalysisByDay.getNumActive();


        //4. 查询7天与30天活跃用户数
        Long day7 = this.getBaseMapper().findNumActiveByDate(ComputeUtil.offsetDay(nowDate, -7), nowDate);
        //5. 创建vo，把数据封装到vo中
        Long day30 = this.getBaseMapper().findNumActiveByDate(ComputeUtil.offsetDay(nowDate, -30), nowDate);
        //6 .返回响应
        AnalysisSummaryVo vo = new AnalysisSummaryVo();
        vo.setCumulativeUsers(numRegistered.longValue()); //累计用户
        vo.setActivePassMonth(day30);//过去30天活跃用户u
        vo.setActivePassWeek(day7);//过去7天活跃用户u
        vo.setNewUsersToday(todayNumRegistered.longValue()); //今日新增用户
        vo.setNewUsersTodayRate(ComputeUtil.computeRate(todayNumRegistered, yesNumRegistered));
        vo.setLoginTimesToday(todayNumLogin.longValue()); //今日登陆次数
        vo.setLoginTimesTodayRate(ComputeUtil.computeRate(todayNumLogin, yesNumLogin));
        vo.setActiveUsersToday(todayNumActive.longValue()); //今日活跃用户数
        vo.setActiveUsersTodayRate(ComputeUtil.computeRate(todayNumActive, yesNumActive));

        return ResponseEntity.ok(vo);


    }

    /**
     * 分析日志表把结果数据更新到日表中
     */
    public void anasysis() {
        //1. 查询日表有没有当前的记录
        String now = DateUtil.formatDate(new Date());
        String yesterday = ComputeUtil.offsetDay(new Date(), -1);
        AnalysisByDay analysisByDay = query().eq("record_date", now).one();
        //2. 如果当前还没有记录，那么插入一个新记录，当天
        if (analysisByDay == null) {
            analysisByDay = new AnalysisByDay();
            analysisByDay.setRecordDate(new Date());
            analysisByDay.setCreated(new Date());
            analysisByDay.setUpdated(new Date());
            save(analysisByDay);
        }

        //3.查询登陆次数、注册人数、活跃人数、次日保留人数
        //今日注册人数
        Long regNum = logMapper.queryNumsByType(now, "0102");
        //今日登陆次数
        Long loginNum = logMapper.queryNumsByType(now, "0101");
        //今日登陆次数
        Long activeNum = logMapper.queryNumsByDate(now);
        //次日保留人数
        Long retention1dNum = logMapper.queryRetention1d(yesterday, now);

        //4. 把数据封装起来，更新到日表中
        analysisByDay.setNumRegistered(regNum.intValue());
        analysisByDay.setNumLogin(loginNum.intValue());
        analysisByDay.setNumActive(activeNum.intValue());
        analysisByDay.setNumRetention1d(retention1dNum.intValue());
        analysisByDay.setUpdated(new Date());
        updateById(analysisByDay);
    }

    public ResponseEntity summaryStatistics(Long sd, Long ed, String type) throws ParseException {
        List<StatisticsVo> thisYearVoList = null;
        List<StatisticsVo> lastYearVoList = null;
        Date lsd = ComputeUtil.offsetMonth(new Date(sd), -12);
        Date led = ComputeUtil.offsetMonth(new Date(ed), -12);
        switch (type) {
            case "101":
                thisYearVoList = getRegisterList(new Date(sd), new Date(ed));
                lastYearVoList = getRegisterList(lsd, led);
                break;
            case "102":
                thisYearVoList = getActiveList(new Date(sd), new Date(ed));
                lastYearVoList = getActiveList(lsd, led);
                break;
            case "103":
                thisYearVoList = getSurvivalRate(new Date(sd),new Date(ed));
                lastYearVoList = getSurvivalRate(lsd, led);
                break;
            default:
                break;
        }

        Map<String, Object> paramMap = new HashMap<>();
        paramMap.put("thisYear", thisYearVoList);
        paramMap.put("lastYear", lastYearVoList);
        return ResponseEntity.ok(paramMap);
    }

    private List<StatisticsVo> getActiveList(Date sd, Date ed) {
        QueryWrapper<AnalysisByDay> wrapper = new QueryWrapper<AnalysisByDay>().select("record_date", "num_active").between("record_date", sd, ed);
        List<AnalysisByDay> list = this.list(wrapper);

        List<StatisticsVo> voList = new ArrayList<>();
        for (AnalysisByDay analysisByDay : list) {
            StatisticsVo statisticsVo = new StatisticsVo();
            Date recordDate = analysisByDay.getRecordDate();
            Integer numActive = analysisByDay.getNumActive();
            statisticsVo.setTitle(new SimpleDateFormat("yyy-MM-dd").format(recordDate));
            statisticsVo.setAmount(numActive);
            voList.add(statisticsVo);
        }
        return voList;
    }

    public List<StatisticsVo> getRegisterList(Date sd, Date ed) {
        QueryWrapper<AnalysisByDay> wrapper = new QueryWrapper<AnalysisByDay>().select("record_date", "num_registered").between("record_date", sd, ed);
        List<AnalysisByDay> list = this.list(wrapper);

        List<StatisticsVo> voList = new ArrayList<>();
        for (AnalysisByDay analysisByDay : list) {
            StatisticsVo statisticsVo = new StatisticsVo();
            Date recordDate = analysisByDay.getRecordDate();
            Integer numRegistered = analysisByDay.getNumRegistered();
            statisticsVo.setTitle(new SimpleDateFormat("yyy-MM-dd").format(recordDate));
            statisticsVo.setAmount(numRegistered);
            voList.add(statisticsVo);
        }
        return voList;
    }

    public List<StatisticsVo> getSurvivalRate(Date sd, Date ed) throws ParseException {
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyy-MM-dd");
        String start = dateFormat.format(sd);
        String end = dateFormat.format(ed);

        QueryWrapper<Log> wrapper = new QueryWrapper<>();
        wrapper.between("log_time",start,end).select("DISTINCT log_time");
        List<Log> logs = logMapper.selectList(wrapper);

        List<StatisticsVo> voList = new ArrayList<>();
        for (Log log : logs) {
            if (log == null) {
                continue;
            }
            String current = log.getLogTime();
            String last = ComputeUtil.offsetDay(dateFormat.parse(current), -1);

            Long registerCount = logMapper.queryNumsByType(last,"0102");
            Long logCount = logMapper.queryRetention1d(last,current);

            int num = 0;
            if (logCount != 0 && registerCount != 0) {
                double v = (logCount.doubleValue() / registerCount.doubleValue()) * 100;
                num = Integer.parseInt((v + "").split("\\.")[0]);
            }
            StatisticsVo vo = new StatisticsVo();
            vo.setTitle(current);
            vo.setAmount(num);
            voList.add(vo);

        }
        return voList;
    }
}
